<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <script>
            var obj111 = {
                aaa: true,
                b: function () {
                    console.log(this, this.aaa);
                }
            };
            obj111.b();
            var bbb = obj111.b;
            bbb();

            var msg = "hell0";
            for (var i = 0; i < 10; i++) {
                console.log(i);
                var msg = "hello" + i * 2 + i;
            }
            console.log("11111111211111111111", msg);
            // 1 let const没有变量提升
            // var 变量提升(提到当前作用域的最顶层)

            // console.log("age", age); //undefied
            // function test() {
            // age =undefind  当前作用域
            //     // var age;
            //     // console.log("age", age); //没有变量提升(暂时性死区)
            //     let age = "王其一";
            // }
            // test();
            //  块级作用域
            // if (true) {
            //     var age1 = 3; //全局作用域
            //     let age2 = 10; //块级作用域
            // }
            // console.log(age1);
            // // console.log(age2);
            // // const声明对象类型为什么能改变内容;const声明常量当是引用类型时检测的是地址指针是否改变
            // const like = "王者荣耀"; //不能改变变量类型.声明即赋值
            // // like = "王者";
            // const obj = { name: "王一一" };
            // obj.name = "王一二";
            // console.log(obj);

            // 2解构赋值
            // 数组的解构 :按照下标对应
            // 对象的解构  :按照属性名对应
            // 函数参数的解构  按照属性名对应
            // let [a, c, [d], f] = [1, 2, [34], 5];
            // console.log(a, c, d, f);
            // let { name1: first, age20: test } = { name1: "王一一", age: 18 };
            // console.log(first, test);
            // let { name1: name1, age: age } = { name1: "王一一", age: 18 };

            // // 字符串新增方法
            // var str = "王一一";
            // var str1 = new String("王一一");
            // String.prototype.suming = function () {
            //     console.log("suming");
            // };
            // str.suming();

            // let s = "Hello world!";

            // console.log(s.startsWith("Hello")); // true
            // console.log(s.startsWith("Heo")); // true
            //
            // includes  判断字符串里面是否存在某个字符  Boolean
            // startsWith  判断字符串是否以某个字符开头  Boolean
            // endsWith  判断字符串是否以某个字符结尾  Boolean
            // trimStart 去除字符串开头的空格
            // trimEnd  去除字符串结尾的空格
            // replaceAll 替换字符串中 所有的 字符

            // 函数的拓展
            // function test() {
            //     // var age;
            //     // console.log("age", age); //没有变量提升(暂时性死区)
            //     console.log(this);
            //     let age = "王其一";
            // }

            // window.test();
            // // 普通函数而言  this的值是谁调用我.指向谁(修改this call apply bind)
            // // 箭头函数的this是在定义的时候.就指向好了.箭头函数没有自己的this;
            // // 箭头函数的this指向于定义时候的外层上下文空间(不能修改this);
            // 箭头函数不能new操作符  没有arguments参数需要编程reset参数方式
            // var sum = (num1, num2) => {
            //     return {
            //         key: num1 + num2
            //     };
            // };
            // console.log(sum(10, 23));

            // function foo() {
            //     console.log("thisfoo", this);
            //     setTimeout(() => {
            //         console.log("thisset", this);

            //         console.log("id:", this.id);
            //     }, 100);
            // }

            // var id = 21;

            // foo.call({ id: 42 });
            // foo.call(window);
            // id: 42
            var arr = [
                1,
                2,
                2,
                3, //20
                4, //30
                5,
                4,
                56,
                56,
                null,
                null,
                undefined,
                undefined
            ];
            // 数据结构 特点:成员值必须是唯一
            // console.log(Array.from(new Set(arr)));
            // console.log([...new Set(arr)]);
            //
            // find 正着寻找第一个符合要求的元素
            // findIndex 正着寻找第一个符合要求的元素下标
            // findLast 倒着寻找第一个符合要求的元素
            // findLastIndex 倒着寻找第一个符合要求的元素的下标
            // console.log([1, 4, -5, -10].findIndex((n) => n < 0));
            // filter

            // splice(开始下标,删除几个,新增)干嘛用  slice方法
            // arr.splice(3, 2, 20, 30); 修改
            // arr.splice(3, 0, 20, 30); //新增

            // arr.splice(3, 2); //删除   改变原数组  涉及到了vue的源码
            // // shift   头部删除
            // // unshift 头部新增      按着头往里塞
            // // pop 尾部删除
            // // push 尾部新增
            //    sort
            //    reverse 改变原数组

            // Array.prototype.sort = function (fn) {
            //     return "墨迹阿婆";
            // };
            // console.log(arr.sort());
            // console.log(arr);
            // var studentArr = [
            //     {
            //         name: "王其一",
            //         age: "20",
            //         like: "篮球,足球,乒乓球",
            //         address: "山东省潍坊市奎文区"
            //     },
            //     {
            //         name: "周子鉴",
            //         age: "22",
            //         like: "篮球,铅球,羽毛球",
            //         address: "河南省郑州市"
            //     },
            //     {
            //         name: "许林超",
            //         age: "24",
            //         like: "跳远,跳绳,羽毛球",
            //         address: "河南省开封市"
            //     },
            //     {
            //         name: "帅振拙",
            //         age: "25",
            //         like: "跑步,羽毛球",
            //         address: "河南省邓州市"
            //     }
            // ];
            // let newarr = studentArr.filter((item) => {
            //     // sdf
            //     if (item.like.indexOf("羽毛球") == -1) {
            //         return item;
            //     }
            //     // console.log(item);
            //     // codeReview
            // });
            // console.log(newarr);
            var arr4 = [[1], 2, 3, [5, 6, [7, 8, 9]]];
            // console.log(arr4.flat(2));
            //  字符串倒置  扁平化数组  深拷贝 截流防抖函数
            Array.prototype.Myflat = function () {
                var resultArr = [];
                // console.log(this); // 指向的是当前实例this=arr4
                // 实现扁平化处理数组
                for (let item of this) {
                    if (Array.isArray(item)) {
                        // console.log(item);
                        resultArr.push(...item.Myflat());
                    } else {
                        resultArr.push(item);
                    }
                    return resultArr;
                }
                // console.log(resultArr);
            };
            console.log(arr4.Myflat());
            // 对象的新增方法
            // Object.assign  浅拷贝  key重名  后面的覆盖前面的  浅拷贝
            // Object.keys   Object.values  Object.entries

            // 错误的写法
            let message = {
                body: {
                    user: { firstName: "zhangsan", lastName: "李四" }
                }
            };
            // const firstName = message.body.user.firstName || "default";
            // 正确的写法
            // const firstName1 =
            //     (message &&
            //         message.body &&
            //         message.body.user &&
            //         message.body.user.firstName) ||
            //     "default";
            const newFirst = message?.body?.user?.firstName || "default";
            console.log("firstName1", newFirst);

            // ES6的链式操作符;
            // ?.判断对象属性存在的情况下往后取值,更安全的取值方式  健壮性
            // ??取默认值的方式
            // let message1 = {
            //     body: {
            //         user: {
            //             firstName: "榴莲",
            //             lastName: "金枕",
            //             kucun: null
            //         }
            //     }
            // };
            // const newFirst1 = message1?.body?.user?.kucun ?? 99;
            // console.log("剩余数量", newFirst1);

            // 新的数据结构   Set Map     数组利用set方法去重   数组循环amp
            // 项目中用的还是比较少 但是我有去看过这些数据结果
            // Set数据结构成员值是唯一的.可以利用这个特性进行数组的去重. 他也有自己的一些方法
            // 比方说size获取长度  add添加数据 delete删除数据  clear清空数据  has判断是否包含数据
            // keys values entries遍历
            // 还有一个weakSet 他要求成员必须是对象类型(弱引用关系)

            // Map数据结构.相比较以前的Object来过.map结构的key值可以是任意类型  而对象的key值只能是
            // 字符串 他也有自己的方法或者属性  size 是长度  set方法是存值
            // get方法是取值  delete方法是删除  clear方法是清空  has方法是判断有没有这个key值
            // keys values entries遍历
            // WeakMap类型里面的key值只能是对象类型(弱引用.可以被垃圾回收机制回收)
            // 在大数据量操作的时候   map结构性能比Object结构的性能更高一些

            // Promise   异步编程的一种方式,相对于以前的回调函数的方式.更加简洁容易理解
            // 三种状态  进行中  已成功 已失败 只能有两种结果 状态凝固

            new Promise(function (resolve, reject) {
                // resolve("返回的正确数据"); //成功的函数
                reject("我错了"); //失败的函数
                console.log("走不走");
            })
                .then((res) => {
                    console.log("成功", res);
                })
                .catch((err) => {
                    console.log("失败", err);
                });
            // .finally(() => {
            //     //无论成功失败都会执行
            //     console.log("无论成功失败都会执行");
            // });

            var p1 = new Promise((resolve, reject) => {
                reject("失败1");
                resolve("成功p1");
            });

            var p2 = new Promise((resolve, reject) => {
                resolve("成功p2");
                reject("失败2");
            });

            var p3 = new Promise((resolve, reject) => {
                reject("失败3");
                resolve("成功p3");
            });

            var p4 = new Promise((resolve, reject) => {
                resolve("成功p4");
                reject("失败");
            });
            // Promise.all方法 接收一个数组,执行多个promise实例,返回一个新的promise实例
            // 只有所有的promise实例都成功,才会执行then方法,否则执行catch方法
            Promise.all([p1, p2, p3, p4])
                .then((res) => {
                    console.log(res); //res是所有成功实例返回数据组成的一个数组
                })
                .catch((err) => {
                    // console.log(err);
                });
            // 执行多个promise实例  返回一个成功状态的promise新实例.在then回调里面接收的是所有实例的一个
            // 状态.无论成功还是失败
            Promise.allSettled([p1, p2, p3, p4])
                .then((res) => {
                    console.log("allSettled then", res); //res是所有实例返回数据组成的一个数组
                })
                .catch((err) => {
                    console.log(err, "永远进不来");
                });
            // Promise.any() 捕获第一个成功的Promise 执行多个promise实例 只要有一个成功的返回的新实例状态就是成功
            Promise.any([p1, p2, p3, p4])
                .then((res) => {
                    console.log("any then", res); //res是所有实例返回数据组成的一个数组
                })
                .catch((err) => {
                    console.log(err, "永远进不来");
                });
            // Promise.race(跑)  执行多个promise实例,返回一个新的promise实例
            // 只要有一个执行完。无论成功还是失败状态 决定了新实例的状态。
            // 成功新实例就是成功。执行完的是失败新实例就是失败状态
            Promise.race([p1, p2, p3, p4])
                .then((res) => {
                    console.log("race then", res); //res是所有实例返回数据组成的一个数组
                })
                .catch((err) => {
                    console.log(err, "永远进不来");
                });

            //  async await 同步的方式实现异步编程 异步编程的终极解决方案
            // 让代码更容易理解和维护
            // 使用的使用直接const result = await getData()
            // 下面就一定能够拿到异步的结果.
            // 如何捕获async await的错误  try catch

            // methods: {
            //  async   getEchartsData(){
            //        const result = await getData()
            //             // 拿到了之后要处理
            //             // 处理

            //

            //     }
            // }
            //         setOptioons({data:result })
            // module语法
            // 抛出                                    导入
            //   export getData   //多个                         import {getData} from './ES6.js' 放到{}中,不能修改名称
            //   export default  //一个                        import ES6 from './ES6.js'   不用放到{}里面 名称可以随意修改

            console.log(1);
            setTimeout(() => {
                Promise.resolve()
                    .then(() => {
                        console.log(5);
                    })
                    .then(() => {
                        console.log(6);
                    });
                console.log(2);
            }, 1000);
            //reject
            setTimeout(() => {
                console.log(3);
                Promise.reject()
                    .then(() => {
                        console.log(7);
                        setTimeout(() => {});
                    })
                    .catch(() => {
                        console.log(8);
                    });
            }, 500);
            console.log(4);
            console.log(111);
        </script>
    </body>
</html>
